/***********************************************************************************
Copy right:      hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include <stdio.h>
#include <modbus.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/shm.h>
#include "msg_queue_peer.h"
#include "shmem.h"

#define KB 1024
#define HTML_SIZE (64 * KB)

// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"

// 与数据上报进程相同的结构定义
union val_t {
    int b_val;   // bool类型存储空间
    int i_val;   // 整形值存储空间
    float f_val; // 浮点值存储空间
};

struct std_node {
    int key;             // 唯一键值
    int type;            // 数据点类型 (0=BOOL, 1=INT, 2=FLOAT)
    int dev_type;        // 设备类型
    union val_t old_val; // 旧值
    union val_t new_val; // 新值
    int ret;             // 状态码
};

// 共享内存参数
static struct shm_param para;
static int *total;                // 节点总数指针
static struct std_node *node_arr; // 节点数组指针

// 静态变量控制初始化次数
static int shm_init_flag = 0;
static pthread_mutex_t shm_mutex = PTHREAD_MUTEX_INITIALIZER;

// 初始化共享内存（只执行一次）
static void init_shared_memory()
{
    pthread_mutex_lock(&shm_mutex);
    if (shm_init_flag == 0) {
        int ret = shm_init(&para, "shm_test", 4096);
        if (ret < 0) {
            perror("shm_init failed");
            pthread_mutex_unlock(&shm_mutex);
            return;
        }

        void *node_p = shm_getaddr(&para);
        if (node_p == NULL) {
            perror("shm_getaddr failed");
            pthread_mutex_unlock(&shm_mutex);
            return;
        }

        total = (int *)node_p;
        node_arr = (struct std_node*)((char*)node_p + sizeof(int));
        shm_init_flag = 1;
        printf("Shared memory initialized successfully\n");
    }
    pthread_mutex_unlock(&shm_mutex);
}

static int handle_login(int sock, const char *input)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username=");//查找字符串是否为包含关系;
    uname += strlen("username=");
    char *p = strstr(input, "password");
    *(p - 1) = '\0';
    printf("username = %s\n", uname);

    char *passwd = p + strlen("password=");
    printf("passwd = %s\n", passwd);

    if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0)
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);
        strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    else
    {
        printf("web login failed\n");

        //"用户名或密码错误"提示
        char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }

    return 0;
}

static int handle_add(int sock, const char *input)
{
    int number1, number2;

    // input必须是"data1=1data2=6"类似的格式
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);

    char reply_buf[HTML_SIZE] = {0};
    printf("sum = %d\n", number1 + number2);
    sprintf(reply_buf, "%d", number1 + number2);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;
}

int handle_read(int sock, const char *input)
{
    // 确保共享内存只初始化一次
    if (shm_init_flag == 0) {
        init_shared_memory();
        if (shm_init_flag == 0) {
            const char *error = "SHM_INIT_FAIL";
            send(sock, error, strlen(error), 0);
            return -1;
        }
    }

    // 验证节点总数
    if (*total <= 0 || *total > 128) {
        char err_msg[50];
        snprintf(err_msg, sizeof(err_msg), "INVALID_NODE_COUNT:%d", *total);
        send(sock, err_msg, strlen(err_msg), 0);
        return -1;
    }

    // 解析前端请求的key值
    int req_key = -1;
    if (sscanf(input, "input=%d", &req_key) != 1) {
        const char *error = "INVALID_INPUT";
        send(sock, error, strlen(error), 0);
        return -1;
    }

    // 在共享内存中搜索匹配的key
    char reply_buf[256] = {0};
    int found = 0;
    for (int i = 0; i < *total; i++) {
        if (node_arr[i].key == req_key) {
            found = 1;
            switch (node_arr[i].type) {
                case 0: // BOOL类型
                    snprintf(reply_buf, sizeof(reply_buf), "%d", node_arr[i].new_val.b_val);
                    break;
                case 1: // INT类型
                    snprintf(reply_buf, sizeof(reply_buf), "%d", node_arr[i].new_val.i_val);
                    break;
                case 2: // FLOAT类型
                    snprintf(reply_buf, sizeof(reply_buf), "%.2f", node_arr[i].new_val.f_val);
                    break;
                default:
                    snprintf(reply_buf, sizeof(reply_buf), "UNKNOWN_TYPE");
            }
            break;
        }
    }

    if (!found) {
        snprintf(reply_buf, sizeof(reply_buf), "KEY_NOT_FOUND");
    }

    // 返回数据到前端
    printf("Returning value: %s\n", reply_buf);
    ssize_t sent = send(sock, reply_buf, strlen(reply_buf), 0);
    if (sent < 0) {
        perror("Send failed");
        return -1;
    }

    return 0;
}

static int handle_write(int sock, const char *input)
{
    typedef struct control
    {
        long dev_type;
        union val_t val;
        int key;
    } con_t, *con_p;
    
    struct control con;
    con.dev_type = 1;

    //sscanf(input, "\"key=%do=%d\"", &con.key, &con.val.b_val);
    sscanf(input, "key=%do=%d", &con.key, &con.val.b_val);
    if (con.key>=300&&con.key<=400)
    {
        con.dev_type = 1;
    }
    else
    {
        con.dev_type = 2;
    }
    
    printf("key=%d val=%d\n", con.key, con.val.b_val);
    printf("写入消息队列\n");
    // 发送消息
    msg_queue_send("topic", &con, sizeof(con), 0);
    
    // 返回成功响应
    const char *success = "WRITE_SUCCESS";
    send(sock, success, strlen(success), 0);
    
    return 0;
}

/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
int parse_and_process(int sock, const char *query_string, const char *input)
{
    // 先处理登录操作
    if (strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
    // 处理求和请求
    else if (strstr(input, "data1=") && strstr(input, "data2="))
    {
        return handle_add(sock, input);
    }
    else if (strstr(input, "input="))
    {
        return handle_read(sock, input);
    }
    else if (strstr(input, "key=") && strstr(input, "o="))
    {
        return handle_write(sock, input);
    }

    return 0;
}